﻿using System;
using System.Collections.Generic;
using System.Windows.Media;
using MVVM_CAD.Model;

namespace MVVM_CAD.Algorithms
{
    public class WuLines
    {
        public static IEnumerable<IPoint> GetLineRepresentation(IPoint begin, IPoint end)
        {
            var knowlegedPoints = new List<IPoint>();
            var x1 = (int)begin.X;
            var y1 = (int)begin.Y;
            var x2 = (int)end.X;
            var y2 = (int)end.Y;
            int dx = (x2 - x1);
            int dy = (y2 - y1);
            int temp;
            float k;
            var color = Colors.Black;
            knowlegedPoints.Add(new CustomPoint(x1, y1));

            if (Math.Abs(dx) > Math.Abs(dy))
            {
                if (dx < 0)
                {
                    temp = x1;
                    x1 = x2;
                    x2 = temp;

                    temp = y1;
                    y1 = y2;
                    y2 = temp;
                }
                k = (float)dy / dx;
                Color bgColor;
                int xs;
                var yt = y1 + k;
                for (xs = x1 + 1; xs < x2; xs++)
                {
                    var distance = yt - (int)(yt);

                    bgColor = GetColorFromKnowlegedPoints(knowlegedPoints, xs, (int)yt);
                    var red   = (byte) ((distance * bgColor.R) + ((1.0f - distance) * color.R));
                    var green = (byte) ((distance * bgColor.G) + ((1.0f - distance) * color.G));
                    var blue  = (byte) ((distance * bgColor.B) + ((1.0f - distance) * color.B));
                    knowlegedPoints.Add(new CustomPoint(xs, yt, Color.FromRgb(red, green, blue)));
                    
                    GetColorFromKnowlegedPoints(knowlegedPoints, xs, (int)yt + 1);
                    red   = (byte) (((1.0f - distance) * bgColor.R) + (distance * color.R));
                    green = (byte) (((1.0f - distance) * bgColor.G) + (distance * color.G));
                    blue  = (byte) (((1.0f - distance) * bgColor.B) + (distance * color.B));
                    knowlegedPoints.Add(new CustomPoint(xs, yt + 1, Color.FromRgb(red, green, blue)));
                    yt += k;
                }
            }
            else
            {
                if (dy < 0)
                {
                    temp = x1;
                    x1 = x2;
                    x2 = temp;

                    temp = y1;
                    y1 = y2;
                    y2 = temp;
                }
                k = dx / (float)dy;

                int ys;
                var xt = x1 + k;
                Color bgColor;
                for (ys = y1 + 1; ys < y2; ys++)
                {
                    var distance = xt - (int)(xt);

                    bgColor = GetColorFromKnowlegedPoints(knowlegedPoints, (int) xt, ys);
                    var red   = (byte) ((distance * bgColor.R) + ((1.0f - distance) * color.R));
                    var green = (byte) ((distance * bgColor.G) + ((1.0f - distance) * color.G));
                    var blue  = (byte) ((distance * bgColor.B) + ((1.0f - distance) * color.B));
                    knowlegedPoints.Add(new CustomPoint(xt, ys, Color.FromRgb(red,green,blue)));

                    bgColor = GetColorFromKnowlegedPoints(knowlegedPoints, (int)xt + 1, ys);
                    red   = (byte) (((1.0f - distance) * bgColor.R) + (distance * color.R));
                    green = (byte) (((1.0f - distance) * bgColor.G) + (distance * color.G));
                    blue  = (byte) (((1.0f - distance) * bgColor.B) + (distance * color.B));
                    knowlegedPoints.Add(new CustomPoint(xt + 1, ys, Color.FromRgb(red, green, blue)));

                    xt += k;
                }
            }
            knowlegedPoints.Add(new CustomPoint(x2, y2));
            return knowlegedPoints;
        }

        private static Color GetColorFromKnowlegedPoints(IEnumerable<IPoint> knowlegedPoints, int x0, int y0)
        {
            foreach (var knowlegedPoint in knowlegedPoints)
            {
                if (knowlegedPoint.X == x0 && knowlegedPoint.Y == y0)
                    return knowlegedPoint.Color;
            }

            return Colors.Black;
        }
    }
}
